<template>
  <div class="game-container">
    <header class="game-header">
      <h1 class="game-title">五子棋游戏</h1>
      <p class="game-status" :class="{ 'winner-animation': config.gameOver }">{{ statusText }}</p>
    </header>
    
    <div class="game-controls">
      <button @click="restartGame" class="btn-game">
        <i class="fa fa-refresh mr-2"></i>重新开始
      </button>
      <button @click="undoMove" class="btn-game" :disabled="config.history.length === 0 || config.gameOver">
        <i class="fa fa-undo mr-2"></i>悔棋
      </button>
    </div>
    
    <div class="board-container">
      <!-- 棋盘外框 -->
      <div id="board" class="board bg-board relative overflow-hidden"
           :style="{ width: boardSize + 'px', height: boardSize + 'px' }"
           @mousemove="handleMouseMove"
           @click="handleBoardClick">
        
        <!-- 棋盘网格线 -->
        <div class="grid-lines absolute inset-0">
          <div v-for="(row, rowIndex) in config.board" :key="rowIndex" class="grid-row h-0">
            <div v-for="(cell, colIndex) in row" :key="colIndex" class="grid-cell inline-block"
                 :style="{ width: config.cellSize + 'px', height: config.cellSize + 'px' }">
              <div class="horizontal-line absolute w-full h-px bg-gray-600/50" style="top: 50%;"></div>
              <div class="vertical-line absolute h-full w-px bg-gray-600/50" style="left: 50%; transform: translateX(-50%);"></div>
            </div>
          </div>
        </div>
        
        <!-- 棋子容器 -->
        <div class="pieces absolute inset-0">
          <div v-for="(row, rowIndex) in config.board" :key="rowIndex" class="relative">
            <div v-for="(cell, colIndex) in row" :key="colIndex" class="absolute">
              <div v-if="cell" 
                   :class="['piece', cell === 'black' ? 'black-piece' : 'white-piece', 
                         isLastMove(rowIndex, colIndex) ? 'last-move' : '']"
                   :style="{ left: (colIndex * config.cellSize - config.pieceRadius) + 'px', 
                           top: (rowIndex * config.cellSize - config.pieceRadius) + 'px',
                           width: (config.pieceRadius * 2) + 'px',
                           height: (config.pieceRadius * 2) + 'px' }">
                <div v-if="isLastMove(rowIndex, colIndex)" class="absolute w-3 h-3 bg-red-500 rounded-full transform -translate-x-1/2 -translate-y-1/2" style="left: 50%; top: 50%;"></div>
              </div>
              
              <!-- 预览棋子 -->
              <div v-if="config.previewPiece.row === rowIndex && config.previewPiece.col === colIndex"
                   :class="['preview-piece', config.currentPlayer === 'black' ? 'black-piece' : 'white-piece']"
                   :style="{ left: (colIndex * config.cellSize - config.pieceRadius) + 'px', 
                           top: (rowIndex * config.cellSize - config.pieceRadius) + 'px',
                           width: (config.pieceRadius * 2) + 'px',
                           height: (config.pieceRadius * 2) + 'px' }">
              </div>
            </div>
          </div>
        </div>
        
        <!-- 棋盘尺寸提示 -->
        <div class="board-size-info absolute bottom-2 right-2 bg-white/80 backdrop-blur-sm px-3 py-1 rounded-md text-sm font-medium">
          当前棋盘大小: {{ boardSize }} x {{ boardSize }} 像素
        </div>
      </div>
    </div>
    
    <div class="mt-8 bg-white/70 backdrop-blur-sm rounded-lg p-4 shadow-md">
      <h3 class="text-lg font-semibold text-primary mb-2">游戏规则</h3>
      <ul class="list-disc pl-5 text-gray-700 space-y-1">
        <li>黑白双方轮流在棋盘上落子</li>
        <li>先在横、竖、斜方向形成五子连珠者获胜</li>
        <li>在预览棋子显示的位置点击即可落子</li>
        <li>边缘区域不可落子</li>
        <li>使用"重新开始"按钮重置游戏</li>
        <li>使用"悔棋"按钮撤销上一步操作</li>
      </ul>
    </div>
  </div>
</template>

<script>
import { ref, reactive, computed, onMounted } from 'vue'

export default {
  name: 'GameView',
  setup() {
    // 游戏配置
    const config = reactive({
      boardSize: 15,        // 棋盘大小 15x15
      cellSize: 40,         // 每个格子的大小(px)
      edgeWidth: 1,         // 边缘宽度(格子数)
      pieceRadius: 18,      // 棋子半径(px)
      currentPlayer: 'black', // 当前玩家 'black' 或 'white'
      gameOver: false,      // 游戏是否结束
      board: [],            // 棋盘状态
      history: [],          // 历史记录
      previewPiece: {       // 预览棋子位置
        row: -1,
        col: -1
      }
    });

    // 鼠标位置
    const mousePosition = ref(null);
    
    // 状态文本
    const statusText = ref('黑方先行');

    // 棋盘大小计算
    const boardSize = computed(() => {
      return config.boardSize * config.cellSize;
    });

    // 初始化棋盘
    const initBoard = () => {
      // 清空棋盘状态和历史记录
      config.board = Array(config.boardSize).fill().map(() => Array(config.boardSize).fill(null));
      config.history = [];
      config.gameOver = false;
      config.currentPlayer = 'black';
      config.previewPiece = { row: -1, col: -1 };
      
      // 更新状态显示
      updateStatus();
    };

    // 检查是否是边缘位置
    const isEdgePosition = (row, col) => {
      return row < config.edgeWidth || 
             row >= config.boardSize - config.edgeWidth || 
             col < config.edgeWidth || 
             col >= config.boardSize - config.edgeWidth;
    };

    // 处理鼠标移动 - 显示预览棋子
    const handleMouseMove = (event) => {
      if (config.gameOver) return;
      
      // 计算鼠标位置对应的行列
      const rect = event.target.getBoundingClientRect();
      const x = event.clientX - rect.left;
      const y = event.clientY - rect.top;
      
      // 计算最近的交叉点
      const col = Math.round(x / config.cellSize);
      const row = Math.round(y / config.cellSize);
      
      // 计算鼠标位置与最近交叉点的距离
      const offsetX = Math.abs(x - (col * config.cellSize));
      const offsetY = Math.abs(y - (row * config.cellSize));
      
      // 判定范围设置为棋子半径，使预览范围与可落子范围一致
      const tolerance = config.pieceRadius;
      
      if (offsetX >= tolerance && offsetY >= tolerance &&
          row >= 0 && row < config.boardSize && 
          col >= 0 && col < config.boardSize && 
          !isEdgePosition(row, col) &&
          config.board[row][col] === null) {
        // 更新预览棋子位置
        config.previewPiece = { row, col };
         
        // 更新鼠标位置显示
        mousePosition.value = {
          x: Math.round(x),
          y: Math.round(y),
          row,
          col
        };
      }
      else {
        // 移除预览棋子位置
        config.previewPiece = { row: -1, col: -1 };
 
      }      
    };

    // 处理棋盘点击
    const handleBoardClick = (event) => {
      if (config.gameOver) return;
      
      // 计算点击位置对应的行列
      const rect = event.target.getBoundingClientRect();
      const x = event.clientX - rect.left;
      const y = event.clientY - rect.top;
      
      // 计算最近的交叉点
      const col = Math.round(x / config.cellSize);
      const row = Math.round(y / config.cellSize);
      
      // 计算鼠标位置与最近交叉点的距离
      const offsetX = Math.abs(x - (col * config.cellSize));
      const offsetY = Math.abs(y - (row * config.cellSize));

      // 判定范围设置为棋子半径，使预览范围与可落子范围一致
      const tolerance = config.pieceRadius;
      
      // 如果预览棋子存在，并且点击在预览范围内，则允许落子
      if (offsetX <= tolerance && offsetY <= tolerance) {
        // 检查位置是否合法
        if (row >= 0 && row < config.boardSize && 
            col >= 0 && col < config.boardSize) {
          // 检查是否是边缘位置
          if (isEdgePosition(row, col)) {
            updateStatus('边缘区域不可落子!');
            setTimeout(updateStatus, 1500); // 1.5秒后恢复正常状态显示
            return;
          }

          // 检查位置是否为空
          if (config.board[row][col] !== null) {
            updateStatus('此位置已有棋子!');
            setTimeout(updateStatus, 1500); // 1.5秒后恢复正常状态显示
            return;
          }
          
          // 合法位置，落子
          placePiece(row, col);
        }
      } else {
        updateStatus('请在预览位置落子!');
        setTimeout(updateStatus, 1500); // 1.5秒后恢复正常状态显示
      }
    };

    // 落子
    const placePiece = (row, col) => {
      // 更新棋盘状态
      config.board[row][col] = config.currentPlayer;
      
      // 记录历史
      config.history.push([row, col, config.currentPlayer]);
      
      // 检查是否获胜
      if (checkWin(row, col)) {
        config.gameOver = true;
        updateStatus(`${config.currentPlayer === 'black' ? '黑方' : '白方'}获胜！`);
        return;
      }
      
      // 检查是否平局
      if (config.history.length === (config.boardSize - 2 * config.edgeWidth) * (config.boardSize - 2 * config.edgeWidth)) {
        config.gameOver = true;
        updateStatus('平局！');
        return;
      }
      
      // 切换玩家
      config.currentPlayer = config.currentPlayer === 'black' ? 'white' : 'black';
      
      // 更新状态
      updateStatus();
    };

    // 检查是否获胜
    const checkWin = (row, col) => {
      const directions = [
        [0, 1],   // 水平
        [1, 0],   // 垂直
        [1, 1],   // 对角线
        [1, -1]   // 反对角线
      ];
      
      const player = config.board[row][col];
      
      for (const [dx, dy] of directions) {
        let count = 1;  // 当前位置已经有一个棋子
        
        // 正方向检查
        for (let i = 1; i < 5; i++) {
          const newRow = row + i * dx;
          const newCol = col + i * dy;
          
          if (newRow < 0 || newRow >= config.boardSize || 
              newCol < 0 || newCol >= config.boardSize || 
              config.board[newRow][newCol] !== player) {
            break;
          }
          
          count++;
        }
        
        // 反方向检查
        for (let i = 1; i < 5; i++) {
          const newRow = row - i * dx;
          const newCol = col - i * dy;
          
          if (newRow < 0 || newRow >= config.boardSize || 
              newCol < 0 || newCol >= config.boardSize || 
              config.board[newRow][newCol] !== player) {
            break;
          }
          
          count++;
        }
        
        // 五子连珠
        if (count >= 5) {
          return true;
        }
      }
      
      return false;
    };

    // 更新状态显示
    const updateStatus = (message) => {
      if (!message) {
        message = `当前回合: ${config.currentPlayer === 'black' ? '黑方' : '白方'}`;
      }
      
      statusText.value = message;
      
      // 添加状态动画
      const statusElement = document.querySelector('.game-status');
      if (statusElement) {
        statusElement.classList.add('animate-pulse');
        setTimeout(() => {
          statusElement.classList.remove('animate-pulse');
        }, 1000);
      }
    };

    // 重新开始游戏
    const restartGame = () => {
      initBoard();
    };

    // 悔棋
    const undoMove = () => {
      if (config.history.length === 0 || config.gameOver) return;
      
      // 移除最后一步
      const lastMove = config.history.pop();
      const [row, col] = lastMove;
      config.board[row][col] = null;
      
      // 切换回上一个玩家
      config.currentPlayer = lastMove[2];
      
      // 更新状态
      updateStatus();
    };

    // 组件挂载后初始化
    onMounted(() => {
      initBoard();
      console.log('棋盘初始化完成:', config.board);
    });

    return {
      config,
      statusText,
      boardSize,
      handleMouseMove,
      handleBoardClick,
      restartGame,
      undoMove,
      isEdgePosition,
      mousePosition
    };
  },
  methods: {
    isLastMove(row, col) {
      if (this.config.history.length === 0) return false;
      const lastMove = this.config.history[this.config.history.length - 1];
      return lastMove[0] === row && lastMove[1] === col;
    }
  }
}
</script>

<style scoped>
.game-container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
  background-color: #f5f5f5;
}

.board-container {
  position: relative;
  width: fit-content;
  margin: 0 auto;
}

.board {
  position: relative;
  border: 3px solid #4a5568;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
  background-color: #f0d9b5;
}

.grid-lines {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  pointer-events: none;
}

.grid-lines::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: repeating-linear-gradient(
    to right,
    #ff0000,
    #ff0000 1px,
    transparent 1px,
    transparent 40px
  );
}

.grid-lines::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: repeating-linear-gradient(
    to bottom,
    #ff0000,
    #ff0000 1px,
    transparent 1px,
    transparent 40px
  );
}

.piece, .preview-piece {
  position: absolute;
  border-radius: 50%;
  transition: transform 0.2s;
}

.black-piece {
  background-color: #000;
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
}

.white-piece {
  background-color: #fff;
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
  border: 1px solid #ccc;
}

.last-move {
  transform: scale(1.1);
}

.btn-game {
  padding: 8px 16px;
  margin-right: 10px;
  background-color: #3b82f6;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.3s;
}

.btn-game:hover {
  background-color: #2563eb;
}

.game-status {
  font-size: 1.2em;
  margin-top: 10px;
  color: #2d3748;
}

.winner-animation {
  animation: pulse 1s infinite;
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.5; }
}
</style>
